package com.yunji.coupon.dao.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.collect.Sets;
import com.yunji.common.base.BaseDaoImpl;
import com.yunji.common.framework.MybatisPlusHelper;
import com.yunji.common.utils.ConvertDataUtil;
import com.yunji.common.utils.JsonUtil;
import com.yunji.common.utils.StringUtils;
import com.yunji.coupon.bo.CouponRunningTmplBO;
import com.yunji.coupon.dao.ICouponTmplDao;
import com.yunji.coupon.doamin.CouponSiteDO;
import com.yunji.coupon.doamin.CouponTmplDO;
import com.yunji.coupon.dto.CouponTmplPageDTO;
import com.yunji.coupon.enums.CouponTmplStatusEnum;
import com.yunji.coupon.mapper.ICouponTmplMapper;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Set;


/**
 * @author : peter-zhu
 * @date : 2024/10/19 16:20
 * @description : TODO
 **/
@Repository
public class CouponTmplDaoImpl extends BaseDaoImpl<ICouponTmplMapper, CouponTmplDO> implements ICouponTmplDao {

    /**
     * @author : peter-zhu
     * @date : 2024/10/24 17:32
     * @description : 领取优惠券时领取数量+1 并且条件带上领取数量不能大于发放数量实现乐观锁
     */
    @Override
    public boolean receiveCoupon(Long id) {
        String receiveCount = MybatisPlusHelper.getColumnName(CouponTmplDO::getReceivedCount);
        // return lambdaUpdate().setSql(receiveCount + "=" + receiveCount + "+1")
        return lambdaUpdate().setSql(MybatisPlusHelper.columnAddCount(CouponTmplDO::getReceivedCount, 1))
                .gtSql(CouponTmplDO::getIssueCount, receiveCount)
                .eq(CouponTmplDO::getCouponTmplId, id).update();
    }

    @Override
    public boolean isReceive(Long id) {
        return lambdaQuery().eq(CouponTmplDO::getCouponTmplId, id).gt(CouponTmplDO::getReceivedCount, 0).count() > 0;
    }

    /**
     * @author : peter-zhu
     * @date : 2024/10/24 17:30
     * @description : 查询出活动中并且未领取完成的优惠券模板
     */
    @Override
    public List<CouponTmplDO> runningTmplList(CouponRunningTmplBO bo) {
        return list(buildStatusLambdaQuery(Sets.newHashSet(CouponTmplStatusEnum.RUNNING.getCode()))
                .apply(StringUtils.isNotEmpty(bo.getTriggerDic()),
                        MybatisPlusHelper.jsonContains(CouponTmplDO::getTriggerDicList, bo.getTriggerDic()))
                .eq(CouponTmplDO::getTriggerType, bo.getTriggerType())
                .eq(CouponTmplDO::isRecallFlag, 0)
                .gtSql(CouponTmplDO::getIssueCount, MybatisPlusHelper.getColumnName((CouponTmplDO::getReceivedCount))));
    }

    /**
     * @author : peter-zhu
     * @date : 2024/10/24 20:04
     * @description : 根据状态构造时间条件
     */
    private static LambdaQueryWrapper<CouponTmplDO> buildStatusLambdaQuery(Set<Integer> statusList) {
        LambdaQueryWrapper<CouponTmplDO> query = new LambdaQueryWrapper<>();
        if (!CollectionUtils.isEmpty(statusList)) {
            Date now = new Date();
            query.and(q -> {
                if (statusList.contains(CouponTmplStatusEnum.UN_START.getCode()))
                    q.or().ge(CouponTmplDO::getReceiveTimeS, now);
                if (statusList.contains(CouponTmplStatusEnum.RUNNING.getCode()))
                    q.or(qr -> {
                        qr.le(CouponTmplDO::getReceiveTimeS, now).ge(CouponTmplDO::getReceiveTimeE, now);
                    });
                if (statusList.contains(CouponTmplStatusEnum.OVER.getCode()))
                    q.or().le(CouponTmplDO::getReceiveTimeE, now);
            });
        }
        return query;
    }

    @Override
    public List<CouponTmplDO> tmplPageList(CouponTmplPageDTO pageParam) {
        return pageList(pageParam, getBuildQueryWrapper(pageParam));
    }

    @Override
    public List<CouponTmplDO> tmplList(CouponTmplPageDTO dto) {
        return list(getBuildQueryWrapper(dto));
    }

    private static LambdaQueryWrapper<CouponTmplDO> getBuildQueryWrapper(CouponTmplPageDTO pageParam) {
        LambdaQueryWrapper<CouponTmplDO> buildQueryWrapper = buildStatusLambdaQuery(pageParam.getStatusList());
        buildQueryWrapper
                .like(StringUtils.isNotEmpty(pageParam.getCouponName()), CouponTmplDO::getCouponName, pageParam.getCouponName())
                .ge(pageParam.getCreateTimeS() != null, CouponTmplDO::getCreateTime, pageParam.getCreateTimeS())
                .le(pageParam.getCreateTimeE() != null, CouponTmplDO::getCreateTime, pageParam.getCreateTimeE()).orderByDesc(CouponTmplDO::getCreateTime);
        return buildQueryWrapper;
    }

    @Override
    public Set<String> likeNames(String name) {
        List<CouponTmplDO> list = lambdaQuery().like(CouponTmplDO::getCouponName, name).select(CouponTmplDO::getCouponName).list();
        return ConvertDataUtil.list2Set(list, CouponTmplDO::getCouponName);
    }

    @Override
    public boolean modifyReceiveTime(Long id, Integer action) {
        Date date = new Date();
        return lambdaUpdate()
                .set(action == 0, CouponTmplDO::getReceiveTimeS, date)
                .set(action == 1, CouponTmplDO::getReceiveTimeE, date)
                .eq(CouponTmplDO::getCouponTmplId, id).update();
    }

    @Override
    public boolean modifyRecall(Long id) {
        return lambdaUpdate().set(CouponTmplDO::isRecallFlag, 1).eq(CouponTmplDO::isRecallFlag, 0).eq(CouponTmplDO::getCouponTmplId, id).update();
    }

    @Override
    public boolean modifyUsedCount(Long couponTmplId, Integer count) {
        String usedCount = MybatisPlusHelper.getColumnName(CouponTmplDO::getUsedCount);
        return lambdaUpdate().setSql(usedCount + "=" + usedCount + "+" + count)
                .eq(CouponTmplDO::getCouponTmplId, couponTmplId).update();
    }

    @Override
    public void testJoin() {
        ICouponTmplMapper baseMapper1 = this.baseMapper;
        List<CouponTmplDO> couponTmplDOS = baseMapper1.selectList(new LambdaQueryWrapper<>());
        System.out.println(JsonUtil.toJsonString(couponTmplDOS));

        MPJLambdaWrapper<CouponTmplDO> wrapper = JoinWrappers.lambda(CouponTmplDO.class)
                .selectAll(CouponTmplDO.class)//查询user表全部字段
                .select(CouponTmplDO::getCouponTmplId)//查询user_address tel 字段
                .selectAs(CouponTmplDO::getCreateTime, CouponTmplDO::getCreateTime)//别名
                .leftJoin(CouponSiteDO.class, CouponSiteDO::getCouponTmplId, CouponTmplDO::getCouponTmplId);

        List<CouponTmplDO> list = baseMapper1.selectJoinList(wrapper);
        System.out.println(JsonUtil.toJsonString(list));
    }
}

